//////////////////////////////////////////////////////////////////////////////////
//                                                                              //
//  This file is part of the buola project (https://code.google.com/p/buola/).  //
//                                                                              //
//  Copyright(c) 2007-2012 Xavi Gratal                                          //
//  gratal AT gmail DOT com                                                     //
//                                                                              //
//  Buola is free software: you can redistribute it and/or modify               //
//  it under the terms of the GNU General Public License as published by        //
//  the Free Software Foundation, either version 3 of the License, or           //
//  (at your option) any later version.                                         //
//                                                                              //
//  Buola is distributed in the hope that it will be useful,                    //
//  but WITHOUT ANY WARRANTY; without even the implied warranty of              //
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               //
//  GNU General Public License for more details.                                //
//                                                                              //
//  You should have received a copy of the GNU General Public License           //
//  along with buola.  If not, see <http://www.gnu.org/licenses/>.              //
//                                                                              //
//////////////////////////////////////////////////////////////////////////////////

#include <buola/buola.h>
#include <buola/app/ccmdline.h>
#include <buola/algorithm/split.h>
#include <buola/io.h>

using namespace buola;

CCmdLineOption<std::string> sNamespaceOption("namespace",L"namespace");
CCmdLineOption<std::string> sNameOption("name",L"name for the variable","mFile");
CCmdLineOption<std::string> sTypeOption("type",L"type to use for text");
CCmdLineFlag sTextOption("text",L"add \\0 at EOF and default type to const char");
CCmdLineFlag sNoStaticOption("no-static",L"don't use static qualifier");

int main(int pArgC,char **pArgs)
{
    buola_init(pArgC,pArgs);

    if(cmd_line().ArgCount()!=2)
    {
        CCmdLine::DisplayHelp();
        return -1;
    }

    io::CTextWriter lOut(io::arg(1),io::EMode::TRUNCATE);
    lOut << "//file generated by bin2hdr from \"" << io::arg(0) << "\"\n\n";

    std::vector<std::string> lNamespaces;
    
    if(cmd_line().IsSet(sNamespaceOption))
    {
        std::string lString=cmd_line().GetValue(sNamespaceOption);
        split(lString,lNamespaces,fn::equal_to(':'),nDeleteEmpty);
    }

    if(!lNamespaces.empty())
    {
        for(int i=0;i<lNamespaces.size();i++)
            lOut << "namespace " << lNamespaces[i] << " { ";
        lOut << "\n\n";
    }
    
    if(!cmd_line().IsSet(sNoStaticOption))
        lOut << "static ";

    if(cmd_line().IsSet(sTypeOption))
        lOut << cmd_line().GetValue(sTypeOption);
    else
    {
        if(cmd_line().IsSet(sTextOption))
            lOut << "const char";
        else
            lOut << "const unsigned char";
    }

    lOut << " " << cmd_line().GetValue(sNameOption) << "[]=\n{";
    
    io::PBufferStream lIn=io::open_buffered(io::arg(0),io::EMode::READ);

    uint8_t lBuffer[1024];

    std::size_t lTotalSize=0;
    
    while(std::size_t lCount=lIn->Read(lBuffer,1024).Count())
    {
        for(std::size_t i=0;i<lCount;i++)
        {
            if(i!=0||lTotalSize!=0)
                lOut << ",";

            if(i%16==0)
                lOut << "\n    ";
            else
                lOut << " ";

            lOut << "0x" << hex_string(lBuffer[i]);
        }

        lTotalSize+=lCount;
    }

    if(cmd_line().IsSet(sTextOption))
    {
        if(lTotalSize>0) lOut << ", ";
        lOut << "0x00";
    }

    lOut << "\n};\n";

    if(!lNamespaces.empty())
    {
        lOut << "\n";
        for(int i=lNamespaces.size()-1;i>=0;i--)
            lOut << "/* namespace " << lNamespaces[i] << " */ } ";
        lOut << "\n";
    }
}
